#include "leveleditormode.h"
#include "editormodemanager.h"
#include "gameObjects/abstractgameobject.h"
#include "levelObjects/level.h"
#include "levelObjects/levelobjectselectionmanager.h"
#include "document.h"
#include "application.h"
#include "widgets/leveleditorview.h"
#include "widgets/mainwindow.h"
#include "widgets/levelEditorWidgets/levelactorpatternswidget.h"
#include "widgets/levelEditorWidgets/leveleditorwidget.h"
#include "widgets/dialogs/levelpropertiesdlg.h"

using namespace Modes;
using namespace LevelModeWidgets;

Modes::LevelEditorMode::LevelEditorMode( EditorModeManager& em )
	: EditorMode("LevelEditorMode", em)
{
	m_levelEditorView = new LevelModeWidgets::LevelEditorView(this);

	initDocks();
	initActions();
	initLevelToolbar();
	createConnections();
}

void Modes::LevelEditorMode::enter()
{
	editorModeManager().mainWindow().setCentralWidget(m_levelEditorView);
	emit populateActorPatternsView();
	m_actorPatternsDock->show();
	m_levelEditorDock->show();
	m_levelEditorView->show();
	editorModeManager().mainWindow().reinitializeGui();
	editorModeManager().mainWindow().menuBar()->addMenu(m_levelMenu);
	m_levelToolbar->show();
}

void Modes::LevelEditorMode::exit()
{
	editorModeManager().mainWindow().takeCentralWidget();
	m_actorPatternsDock->hide();
	m_levelEditorDock->hide();
	m_levelEditorView->hide();
	editorModeManager().mainWindow().reinitializeGui();
	m_levelToolbar->hide();
}

void Modes::LevelEditorMode::updateGui()
{
	m_addActorAct->setEnabled(m_selectedLevel != 0);
}

void Modes::LevelEditorMode::onDocumentChanged( QPointer<Document> doc )
{
	emit documentChanged(doc);

	if(doc)
	{
		connect(doc, &Document::levelCreated, this, &Modes::LevelEditorMode::levelCreated);
		connect(doc, &Document::levelDeleted, this, &Modes::LevelEditorMode::levelDeleted);
	}

	updateGui();
	m_levelEditorView->update();
}

void Modes::LevelEditorMode::initDocks()
{
	m_actorPatternsDock = new QDockWidget("Actor Patterns");
	m_actorPatternsDock->setAllowedAreas(Qt::LeftDockWidgetArea);
	LevelActorPatternsWidget* pLAPW = new LevelActorPatternsWidget(this);
	m_actorPatternsDock->setWidget(pLAPW);

	m_levelEditorDock = new QDockWidget("Level editor");
	m_levelEditorDock->setAllowedAreas(Qt::RightDockWidgetArea);
	LevelEditorWidget* pLEW = new LevelEditorWidget(this);
	m_levelEditorDock->setWidget(pLEW);

	editorModeManager().mainWindow().addDockWidget(Qt::LeftDockWidgetArea, m_actorPatternsDock);
	editorModeManager().mainWindow().addDockWidget(Qt::RightDockWidgetArea, m_levelEditorDock);
	m_actorPatternsDock->hide();
	m_levelEditorDock->hide();
}

void Modes::LevelEditorMode::initActions()
{
	m_levelMenu = new QMenu("Level");
	m_createLevelAct = m_levelMenu->addAction("Create Level");
	m_addActorAct = m_levelMenu->addAction("Add Actor");
	m_deleteLevelObjectAct = m_levelMenu->addAction("Delete Selection");
}

void Modes::LevelEditorMode::initLevelToolbar()
{
	m_levelToolbar = new QToolBar;
	m_levelToolbar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
	QFont ltbFont = m_levelToolbar->font();
	ltbFont.setPixelSize(9);
	m_levelToolbar->setFont(ltbFont);
	m_levelToolbar->addAction(m_createLevelAct);
	m_levelToolbar->addAction(m_addActorAct);
	m_levelToolbar->addAction(m_deleteLevelObjectAct);
	editorModeManager().mainWindow().addToolBar(Qt::TopToolBarArea, m_levelToolbar);
	m_levelToolbar->hide();
}

void Modes::LevelEditorMode::createConnections()
{
	connect(m_createLevelAct, &QAction::triggered, 
		this, &Modes::LevelEditorMode::onCreateLevel);
	connect(m_addActorAct, &QAction::triggered, 
		this, &Modes::LevelEditorMode::onAddActor);
	connect(m_deleteLevelObjectAct, &QAction::triggered, 
		this, &Modes::LevelEditorMode::onDeleteActor);
}

void Modes::LevelEditorMode::onSelectedLevelChanged( QPointer<LevelObjects::AbstractLevelObject> lo )
{
	if(m_selectedLevel)
	{
		QPointer<LevelObjects::Level> level = qobject_cast<LevelObjects::Level*>(m_selectedLevel);
		disconnect(level->selectionManager(), &LevelObjects::LevelObjectSelectionManager::objectSelectionChanged, 
			this, &Modes::LevelEditorMode::onObjectSelectionChanged);
	}

	m_selectedLevel = lo;

	if(m_selectedLevel)
	{
		QPointer<LevelObjects::Level> level = qobject_cast<LevelObjects::Level*>(m_selectedLevel);
		connect(level->selectionManager(), &LevelObjects::LevelObjectSelectionManager::objectSelectionChanged, 
			this, &Modes::LevelEditorMode::onObjectSelectionChanged);
	}

	emit selectedLevelChanged(m_selectedLevel);

	updateGui();
	m_levelEditorView->update();
}

void Modes::LevelEditorMode::onCreateLevel()
{
	LevelPropertiesDlg dlg;
	dlg.exec();
}

void Modes::LevelEditorMode::onAddActor()
{
	Q_ASSERT(m_selectedLevel);
	Q_ASSERT(m_selectedActorPattern);
	QPointer<LevelObjects::Level> level = qobject_cast<LevelObjects::Level*>(m_selectedLevel);
	level->createLevelObject("", m_selectedActorPattern);

	// TODO: update view on other place
	updateGui();
	m_levelEditorView->update();
}

void Modes::LevelEditorMode::onDeleteLevel()
{

}

void Modes::LevelEditorMode::onDeleteActor()
{

}

void Modes::LevelEditorMode::onSelectedActorPatternChanged( QPointer<AbstractGameObject> go )
{
	if(m_selectedActorPattern != go)
	{
		m_selectedActorPattern = go;
	}
}

QPointer<LevelObjects::AbstractLevelObject> Modes::LevelEditorMode::selectedLevel() const
{
	return m_selectedLevel;
}

void Modes::LevelEditorMode::onObjectSelectionChanged()
{
	m_levelEditorView->update();
	updateGui();
}
